﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Cyl.Communication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using VisionApp.Core.Models;
using VisionApp.PostProcess.Net8;
using VisionApp.PreProcess.Net8;
using VisionApp.Startup.Models;
using VisionApp.Startup.Services;
using VisionApp.UserManager.Service;
using VM.Core;
using VM.PlatformSDKCS;
using VMControls.WPF.Release;

namespace VisionApp.Startup.ViewModels;

public partial class VisionAppViewModel : ObservableObject
{
    private readonly IPreProcessService preProcessService;
    private readonly IPostProcessService postProcessService;
    private readonly AlgoManager algoManager;
    private readonly CommunicationService communicationService;
    private readonly IUserManagerService userManagerService;
    private readonly IConfiguration configuration;
    private readonly ILogger<VisionAppViewModel> logger;

    private List<ProductModel> _ProductList;
    private List<AlgorithmModel> _AlgoList;

    private string? _cameraName;

    private static readonly List<string> _cameraNameList = new();// 防错，控件的名字重复

    private string plcIP;
    private ICommDevice commDevice;
    private Dictionary<string ,object> parameters = new Dictionary<string ,object>();

    [ObservableProperty]
    private int toolbarHeight = 0;
    [ObservableProperty]
    private bool canTakePhoto=false;
    public VisionAppViewModel(IPreProcessService preProcessService, IPostProcessService postProcessService, AlgoManager algoManager, CommunicationService communicationService,IUserManagerService userManagerService, IConfiguration configuration, ILogger<VisionAppViewModel> logger)
    {
        this.preProcessService = preProcessService;
        this.postProcessService = postProcessService;
        this.algoManager = algoManager;
        this.communicationService = communicationService;
        this.userManagerService = userManagerService;
        this.configuration = configuration;
        this.logger = logger;

        this.userManagerService.OnUserChanged += UserManagerService_OnUserChanged;
        this.algoManager.OnProductLoaded += AlgoManager_OnProductLoaded;

        this._ProductList = algoManager.GetProductList();
        this._AlgoList = algoManager.GetAlgoList();

        VmSolution.OnWorkStatusEvent += VmSolution_OnWorkStatusEvent;

        // 全局配置
        this.plcIP= configuration.GetValue<string>("PlcIP");

        //RegisterCameraEvents();
        RegisterCommunicationEvents();
                
    }
    // 切换产品后，重新关联显示
    private void AlgoManager_OnProductLoaded(object? sender, EventArgs e)
    {
        ConnectAlgoAndControl();
    }

    private void ConnectAlgoAndControl()
    {
        var proc = _AlgoList.Find(a => a.CameraName == _cameraName)?.VmProcedure;
        Application.Current.Dispatcher.Invoke(() =>
        {
            _vmRenderControl.ModuleSource = proc;
        });
    }

    private void UserManagerService_OnUserChanged(object? sender, UserDto e)
    {
        Application.Current.Dispatcher.Invoke(() =>
        {
            currentUser = e;
            ToolbarHeight = currentUser.Level > UserLevel.user ? 50 : 0;
        });
    }

    private void RegisterCommunicationEvents()
    {

        this.communicationService.OnTrigSignalChanged += CommunicationService_OnTrigSignalChanged;
        this.commDevice= this.communicationService.GetCommDevice(this.plcIP);
    }

    private UserDto currentUser;

    [RelayCommand]
    public void ViewLoaded(string cameraName)
    {
        if (string.IsNullOrEmpty(cameraName) || cameraName == "VisionAppView")
        {
            logger.LogError("VisionAppView-摄像头名称不能为空");
            return;
        }
        // 查找控件名称是否重复
        if (_cameraNameList.Contains(cameraName))
        {
            logger.LogError($"VisionAppView-相机名称不能重复，请修改控件的Name属性");
            return;
        }
        _cameraNameList.Add(cameraName);
        _cameraName = cameraName;
        ConnectAlgoAndControl();
    }

    private void CommunicationService_OnTrigSignalChanged(object? sender, string e)
    {
        if (_cameraName != e) return;// 不是当前相机的触发信号
        var algo = _AlgoList.Find(a => a.CameraName == e);
        if (algo == null)
        {
            logger.LogError($"{e}关联的算法不存在。");
            return;
        }
        //  预处理程序
        var para= preProcessService.GetParameters(this.commDevice);
        string paraStr="";
        if (para != null) {
            paraStr=string.Join(",",para.Values);
        }
        algo.VmProcedure.LocalVariable.SetVarString("para", [paraStr]);
        //algo.VmProcedure.Inputs["SN"].Value = "1234567890";
        algo.VmProcedure.Run();
    }



    private void VmSolution_OnWorkStatusEvent(ImvsSdkDefine.IMVS_MODULE_WORK_STAUS workStatusInfo)
    {

        if (workStatusInfo.nWorkStatus != 0) return;
        var algo = _AlgoList.Find(a => a.ID == workStatusInfo.nProcessID);
        if (algo.CameraName != _cameraName) return;
        if (algo == null) return;

        // 获取结果
        var isok = !algo.VmProcedure.IsProcessRunStop;
        var processTime = algo.VmProcedure.ModuResult.ModuRunTime;

        // 填充结果
        var result = new InspectionResult()
        {
            AlogrithmName = algo.Name,
            CameraName = algo.CameraName,
            ErrorMessage = "", 
            IsOk = isok, ProcessingTimeMs = processTime,
            Result = new Dictionary<string, object>()
        };
        var ioNameInfos = algo.VmProcedure.ModuResult.GetAllOutputNameInfo();
        foreach (var info in ioNameInfos)
        {
            switch (info.TypeName)
            {
                case IMVS_MODULE_BASE_DATA_TYPE.IMVS_GRAP_TYPE_FLOAT:
                    float floatR;
                    try
                    {
                        floatR = algo.VmProcedure.ModuResult.GetOutputFloat(info.Name).pFloatVal[0];
                    }
                    catch
                    {
                        floatR = 0;
                    }
                    result.Result.Add(info.Name, floatR);
                    break;
                case IMVS_MODULE_BASE_DATA_TYPE.IMVS_GRAP_TYPE_STRING:
                    string strR;
                    try
                    {
                        strR = algo.VmProcedure.ModuResult.GetOutputString(info.Name).astStringVal[0].strValue;

                    }
                    catch (Exception)
                    {
                        strR = "";
                    }
                    result.Result.Add(info.Name, strR);
                    break;
                case IMVS_MODULE_BASE_DATA_TYPE.IMVS_GRAP_TYPE_DOUBLE:
                    float doubleR;
                    try
                    {
                        doubleR = algo.VmProcedure.ModuResult.GetOutputFloat(info.Name).pFloatVal[0];

                    }
                    catch (Exception)
                    {
                        doubleR = 0;
                    }
                    result.Result.Add(info.Name, doubleR);
                    break;
                case IMVS_MODULE_BASE_DATA_TYPE.IMVS_GRAP_TYPE_INT:
                    int intR;
                    try
                    {
                        intR = algo.VmProcedure.ModuResult.GetOutputInt(info.Name).pIntVal[0];
                    }
                    catch (Exception)
                    {
                        intR = 0;
                    }
                    result.Result.Add(info.Name, intR);
                    break;
                default:
                    logger.LogWarning("数据类型无法解析");
                    break;
            }
        }

        Debug.WriteLine($"{result.IsOk}-{result.ProcessingTimeMs}");
        // 发送结果
        postProcessService.ProcessResults(result, this.commDevice);
    }
    private VmRenderControl _vmRenderControl;
    public void SetWindowHandle(VmRenderControl vmRenderControl) {
        _vmRenderControl= vmRenderControl;
    }
}
